from register_file import *
from data_type import *


def sign_expend(x, len):
    if x & (1 << len - 1):
        return x - (1 << len)
    else:
        return x


def mask(n):
    return (1 << n) - 1


def get_bit(x, L, R):
    return x >> R & mask(L - R + 1)


class type:
    def __init__(self):
        self.name = ""
        self.float = False
        self.size = 0  # 0 -> dw, 1 -> w, 2 -> h, 3 -> b, 4 -> s.d, 5 -> d.wu, 6 -> wu.d, 7 -> l.d, 8 ->d.l,
        # 9 -> w.d, 10 -> d.w, 11 -> d.x, 12 -> x.d
        self.do = 0  # 0 -> reg, 1 -> save, 2 -> load, 3 -> branch
        self.imm = False
        self.unsigned = False
        self.wb = False
        self.stack = False


def decoder_16(instr):
    job = type()
    rs1 = 0
    rs2 = 0
    rd = 0
    imm = 0
    job.imm = False

    opcode = instr & 0b11

    if opcode == 0b01:
        funct3 = (instr >> 13) & 0b111
        idx_12 = (instr >> 12) & 0b1
        idx_117 = (instr >> 7) & 0b11111
        idx_62 = (instr >> 2) & 0b11111
        idx_1210 = (instr >> 10) & 0b111
        idx_97 = (instr >> 7) & 0b111
        if funct3 == 0b000:
            if idx_117 == 0:
                job.name = ""  # nop
                job.do = 4
            else:
                job.name = "add"  # addi
                job.imm = True
                rs1 = rd = idx_117
                imm_pre = (idx_12 << 5) | idx_62
                imm = sign_expend(imm_pre, 6)
        elif funct3 == 0b001:
            job.name = "add"  # addiw
            job.size = 1
            job.imm = True
            rs1 = rd = idx_117
            imm_pre = (idx_12 << 5) | idx_62
            imm = sign_expend(imm_pre, 6)
        elif funct3 == 0b010:
            job.name = "add"  # li
            job.imm = True
            rd = idx_117
            rs1 = 0
            imm_pre = (idx_12 << 5) | idx_62
            imm = sign_expend(imm_pre, 6)
        elif funct3 == 0b011:
            if idx_117 == 2:
                job.name = "add"  # addi16sp
                job.imm = True
                rd = rs1 = 2
                imm_pre = (idx_12 << 9) | (get_bit(idx_62, 2, 1) << 7) | (get_bit(idx_62, 3, 3) << 6) | (
                        get_bit(idx_62, 0, 0) << 5) | (get_bit(idx_62, 4, 4) << 4)
                imm = sign_expend(imm_pre, 10)
            else:
                job.name = "lui"
                job.imm = True
                job.do = 4
                rd = idx_117
                imm_pre = (idx_12 << 17) | (idx_62 << 12)
                imm = sign_expend(imm_pre, 18)
        elif funct3 == 0b100:
            idx_1110 = (instr >> 10) & 0b11
            if idx_1110 == 0b00:
                job.name = "srl"  # srl
                job.imm = True
                rs1 = rd = idx_97 + 8
                imm_pre = (idx_12 << 5) | idx_62
                imm = imm_pre
            elif idx_1110 == 0b01:
                job.name = "sra"  # srai
                job.imm = True
                rs1 = rd = idx_97 + 8
                imm_pre = (idx_12 << 5) | idx_62
                imm = imm_pre
            elif idx_1110 == 0b10:
                job.name = "and"  # andi
                job.imm = True
                rs1 = rd = idx_97 + 8
                imm_pre = (idx_12 << 5) | idx_62
                imm = sign_expend(imm_pre, 6)
            else:
                idx_65 = (instr >> 5) & 0b11
                idx_42 = (instr >> 2) & 0b111
                if idx_12 == 1:
                    if idx_65 == 0b01:
                        job.name = "add"  # addw
                        job.size = 1
                        rd = rs1 = idx_97 + 8
                        rs2 = idx_42 + 8
                    elif idx_65 == 0b00:
                        job.name = "sub"  # subw
                        job.size = 1
                        rd = rs1 = idx_97 + 8
                        rs2 = idx_42 + 8
                elif idx_65 == 0b00:
                    job.name = "sub"
                    rs1 = rd = idx_97 + 8
                    rs2 = idx_42 + 8
                elif idx_65 == 0b01:
                    job.name = "xor"
                    rs1 = rd = idx_97 + 8
                    rs2 = idx_42 + 8
                elif idx_65 == 0b10:
                    job.name = "or"
                    rs1 = rd = idx_97 + 8
                    rs2 = idx_42 + 8
                else:
                    job.name = "and"
                    rs1 = rd = idx_97 + 8
                    rs2 = idx_42 + 8
        elif funct3 == 0b101:
            job.name = "jal"  # j
            job.do = 3
            job.imm = True
            rd = 0
            temp = (instr >> 2) & 0b11111111111
            imm_pre = (get_bit(temp, 10, 10) << 11) | (get_bit(temp, 6, 6) << 10) | (get_bit(temp, 8, 7) << 8) | (
                    get_bit(temp, 4, 4) << 7) | (get_bit(temp, 5, 5) << 6) | (get_bit(temp, 0, 0) << 5) | (
                              get_bit(temp, 9, 9) << 4) | (get_bit(temp, 3, 1) << 1)
            imm = sign_expend(imm_pre, 12)
        elif funct3 == 0b110:
            job.name = "beq"  # beqz
            job.do = 3
            job.imm = True
            rs1 = idx_97 + 8
            rs2 = 0
            imm_pre = (get_bit(idx_1210, 2, 2) << 8) | (get_bit(idx_62, 4, 3) << 6) | (get_bit(idx_62, 0, 0) << 5) | (
                    get_bit(idx_1210, 1, 0) << 3) | (get_bit(idx_62, 2, 1) << 1)
            imm = sign_expend(imm_pre, 9)
        else:
            job.name = "bne"  # bnez
            job.do = 3
            job.imm = True
            rs1 = idx_97 + 8
            rs2 = 0
            imm_pre = (get_bit(idx_1210, 2, 2) << 8) | (get_bit(idx_62, 4, 3) << 6) | (get_bit(idx_62, 0, 0) << 5) | (
                    get_bit(idx_1210, 1, 0) << 3) | (get_bit(idx_62, 2, 1) << 1)
            imm = sign_expend(imm_pre, 9)
    elif opcode == 0b00:
        funct3 = (instr >> 13) & 0b111
        idx_42 = (instr >> 2) & 0b111
        idx_1210 = (instr >> 10) & 0b111
        idx_97 = (instr >> 7) & 0b111
        idx_65 = (instr >> 5) & 0b11
        if funct3 == 0b000:
            idx_125 = (instr >> 5) & 0xff
            if idx_125 == 0:
                job.name = 'illegal'
                job.do = 4
            else:
                job.name = "add"  # add
                job.imm = True
                rd = idx_42 + 8
                rs1 = 2
                uimm_pre = (get_bit(idx_125, 5, 2) << 6) | (get_bit(idx_125, 7, 6) << 4) | (
                        get_bit(idx_125, 0, 0) << 3) | (get_bit(idx_125, 1, 1) << 2)
                imm = uimm_pre
        elif funct3 == 0b001:
            job.name = "fld"
            job.imm = True
            job.do = 2
            job.float = True
            rs1 = idx_97 + 8
            if rs1 == 2:
                job.stack = True
            rd = idx_42 + 8
            uimm_pre = (idx_65 << 6) | (idx_1210 << 3)
            imm = uimm_pre
        elif funct3 == 0b010:
            job.name = "lw"
            job.imm = True
            job.do = 2
            job.size = 1
            rs1 = idx_97 + 8
            if rs1 == 2:
                job.stack = True
            rd = idx_42 + 8
            uimm_pre = (get_bit(idx_65, 0, 0) << 6) | (idx_1210 << 3) | (get_bit(idx_65, 1, 1) << 2)
            imm = uimm_pre
        elif funct3 == 0b011:
            job.name = "ld"
            job.imm = True
            job.do = 2
            rs1 = idx_97 + 8
            if rs1 == 2:
                job.stack = True
            rd = idx_42 + 8
            uimm_pre = (idx_65 << 6) | (idx_1210 << 3)
            imm = uimm_pre
        elif funct3 == 0b101:
            job.name = "fsd"
            job.imm = True
            job.float = True
            job.do = 1
            rs1 = idx_97 + 8
            rs2 = idx_42 + 8
            uimm_pre = (idx_65 << 6) | (idx_1210 << 3)
            imm = uimm_pre
        elif funct3 == 0b110:
            job.name = "sw"
            job.imm = True
            job.do = 1
            job.size = 1
            rs1 = idx_97 + 8
            rs2 = idx_42 + 8
            if rs1 == 2:
                job.stack = True
            uimm_pre = (get_bit(idx_65, 0, 0) << 6) | (idx_1210 << 3) | (get_bit(idx_65, 1, 1) << 2)
            imm = uimm_pre
        elif funct3 == 0b111:
            job.name = "sd"
            job.do = 1
            rs1 = idx_97 + 8
            if rs1 == 2:
                job.stack = True
            rs2 = idx_42 + 8
            uimm_pre = (idx_65 << 6) | (idx_1210 << 3)
            imm = uimm_pre
    elif opcode == 0b10:
        funct3 = (instr >> 13) & 0b111
        idx_117 = (instr >> 7) & 0b11111
        idx_12 = (instr >> 12) & 0b1
        idx_62 = (instr >> 2) & 0b11111
        idx_127 = (instr >> 7) & 0b111111
        if funct3 == 0b000:
            job.name = "sll"  # slli
            job.imm = True
            rs1 = rd = idx_117
            uimm_pre = (idx_12 << 5) | idx_62
            imm = uimm_pre
        elif funct3 == 0b001:
            job.name = "fld"  # fldsp ==============================================
            job.imm = True
            job.float = True
            job.do = 2
            rd = idx_117
            rs1 = 2
            job.stack = True
            uimm_pre = (get_bit(idx_62, 2, 0) << 6) | (idx_12 << 5) | (get_bit(idx_62, 4, 3) << 3)
            imm = uimm_pre
        elif funct3 == 0b010:
            job.name = "lw"  # lwsp ================================================
            job.imm = True
            job.do = 2
            job.size = 1
            rd = idx_117
            rs1 = 2
            job.stack = True
            uimm_pre = (get_bit(idx_62, 2, 0) << 6) | (idx_12 << 5) | (get_bit(idx_62, 4, 3) << 2)
            imm = uimm_pre
        elif funct3 == 0b011:
            job.name = "ld"  # ldsp ================================================
            job.imm = True
            job.do = 2
            rd = idx_117
            rs1 = 2
            job.stack = True
            uimm_pre = (get_bit(idx_62, 2, 0) << 6) | (idx_12 << 5) | (get_bit(idx_62, 4, 3) << 3)
            imm = uimm_pre
        elif funct3 == 0b100:
            if not idx_12:
                if idx_62 == 0:
                    job.name = "jalr"  # jr
                    job.imm = False
                    job.do = 3
                    rs1 = idx_117
                    rd = 0
                else:
                    job.name = "add"  # mv =========================================
                    job.imm = False
                    rd = idx_117
                    rs1 = 0
                    rs2 = idx_62
            else:
                if idx_62 == 0:
                    job.name = "jalr"
                    job.imm = False
                    job.do = 3
                    rs1 = idx_117
                    rd = 1
                else:
                    job.name = "add"
                    job.imm = False
                    rd = rs1 = idx_117
                    rs2 = idx_62
        elif funct3 == 0b101:
            job.name = "fsd"  # fsdsp ==============================================
            job.imm = True
            job.do = 1
            job.float = True
            rs1 = 2
            job.stack = True
            rs2 = idx_62
            uimm_pre = (get_bit(idx_127, 2, 0) << 6) | (get_bit(idx_127, 5, 3) << 3)
            imm = uimm_pre
        elif funct3 == 0b110:
            job.name = "sw"  # swsp ================================================
            job.imm = True
            job.do = 1
            job.size = 1
            rs1 = 2
            job.stack = True
            rs2 = idx_62
            uimm_pre = (get_bit(idx_127, 1, 0) << 6) | (get_bit(idx_127, 5, 2) << 2)
            imm = uimm_pre
        elif funct3 == 0b111:
            job.name = "sd"  # sdsp ================================================
            job.imm = True
            job.do = 1
            rs1 = 2
            job.stack = True
            rs2 = idx_62
            uimm_pre = (get_bit(idx_127, 2, 0) << 6) | (get_bit(idx_127, 5, 3) << 3)
            imm = uimm_pre

    return job, rs1, rs2, rd, imm


I = (0b0010011, 0b0000011, 0b1100111, 0b1110011, 0b0000111, 0b0011011)


def decoder_32(instr):
    job = type()
    rs1 = 0
    rs2 = 0
    rd = 0
    imm = 0
    job.imm = False
    opcode = instr & 0b1111111
    if opcode == 0b0110011:  # R-type
        funct7 = get_bit(instr, 31, 25)
        funct3 = get_bit(instr, 14, 12)
        rs2 = get_bit(instr, 24, 20)
        rs1 = get_bit(instr, 19, 15)
        rd = get_bit(instr, 11, 7)
        if funct3 == 0b000:
            if funct7 == 0x00:
                job.name = "add"
            elif funct7 == 0x01:
                job.name = "mul"
            elif funct7 == 0x20:
                job.name = "sub"
        elif funct3 == 0b001:
            job.name = "sll"
        elif funct3 == 0b010:
            job.name = "slt"
        elif funct3 == 0b011:
            if funct7 == 0x00:
                job.name = "slt"  # sltu
                job.unsigned = True
            elif funct7 == 0x01:
                job.name = "mulh"  # mulhu
                job.unsigned = True
        elif funct3 == 0b100:
            job.name = "xor"
        elif funct3 == 0b101:
            if funct7 == 0x00:
                job.name = "srl"
            elif funct7 == 0x01:
                job.name = "div"  # divu
                job.unsigned = True
            elif funct7 == 0x20:
                job.name = "sra"
        elif funct3 == 0b110:
            job.name = "or"
        elif funct3 == 0b111:
            if funct7 == 0x00:
                job.name = "and"
            elif funct7 == 0x01:
                job.name = "rem"  # remu
                job.unsigned = True
    elif opcode == 0b1010011:
        rs2 = get_bit(instr, 24, 20)
        rs1 = get_bit(instr, 19, 15)
        rd = get_bit(instr, 11, 7)
        funct3 = get_bit(instr, 14, 12)
        funct5 = get_bit(instr, 31, 27)
        fmt = get_bit(instr, 26, 25)
        if funct5 == 0b00000:
            if fmt == 0b00:
                job.name = "fadd.s"
                job.float = True
                job.size = 1
            elif fmt == 0b01:
                job.name = "fadd.d"
                job.float = True
        elif funct5 == 0b00001:
            if fmt == 0b00:
                job.name = "fsub.s"
                job.float = True
                job.size = 1
            elif fmt == 0b01:
                job.name = "fsub.d"
                job.float = True
        elif funct5 == 0b00010:
            if fmt == 0b00:
                job.name = "fmul.s"
                job.float = True
                job.size = 1
            elif fmt == 0b01:
                job.name = "fmul.d"
                job.float = True
        elif funct5 == 0b00011:
            if fmt == 0b00:
                job.name = "fdiv.s"
                job.float = True
                job.size = 1
            elif fmt == 0b01:
                job.name = "fdiv.d"
                job.float = True
        elif funct5 == 0b11010:
            if rs2 == 0b00010:
                job.name = "fcvt.d.l"
                job.size = 8
            elif rs2 == 0b00000:
                job.name = "fcvt.d.w"
                job.size = 10
            elif rs2 == 0b00001:
                job.name = "fcvt.d.wu"
                job.size = 5
        elif funct5 == 0b11000:
            if rs2 == 0b00000:
                job.name = "fcvt.w.d"
            elif rs2 == 0b00001:
                job.name = "fcvt.wu.d"
            elif rs2 == 0b00010:
                job.name = "fcvt.l.d"
        elif funct5 == 0b01000:
            if rs2 == 0b00001:
                job.name = "fcvt.s.d"
        elif funct5 == 0b11110:  # 还有.w.x跟fmt有关
            job.name = "fmv.d.x"
        elif funct5 == 0b11100:
            job.name = "fmv.x.d"
        elif funct5 == 0b00100:
            if funct3 == 0b000:
                if fmt == 0b01:
                    job.name = "fsgnj.d"
                elif fmt == 0b00:
                    job.name = "fsgnj.s"
            elif funct3 == 0b001:
                if fmt == 0b01:
                    job.name = "fsgnjn.d"
                elif fmt == 0b00:
                    job.name = "fsgnjn.s"
            elif funct3 == 0b010:
                if fmt == 0b01:
                    job.name = "fsgnjx.d"
                elif fmt == 0b00:
                    job.name = "fsgnjx.s"
        elif funct5 == 0b10100:
            if funct3 == 0b010:
                if fmt == 0b01:
                    job.name = "feq.d"
                elif fmt == 0b00:
                    job.name = "feq.s"
            elif funct3 == 0b001:
                if fmt == 0b01:
                    job.name = "flt.d"
                elif fmt == 0b00:
                    job.name = "flt.s"
            elif funct3 == 0b000:
                if fmt == 0b01:
                    job.name = "fle.d"
                elif fmt == 0b00:
                    job.name = "fle.s"
    elif opcode == 0b1000011:
        rs2 = get_bit(instr, 24, 20)
        rs1 = get_bit(instr, 19, 15)
        rs3 = get_bit(instr, 31, 27)
        rd = get_bit(instr, 11, 7)
        fmt = get_bit(instr, 26, 25)
        if fmt == 0b01:
            job.name = "fmadd.d"
        elif fmt == 0b00:
            job.name = "fmadd.s"
    elif opcode == 0b0111011:
        rs1 = get_bit(instr, 19, 15)
        rs2 = get_bit(instr, 24, 20)
        rd = get_bit(instr, 11, 7)
        funct3 = get_bit(instr, 14, 12)
        funct7 = get_bit(instr, 31, 25)
        if funct7 == 0b0000001:
            if funct3 == 0b000:
                job.name = "mul"  # mulw
                job.size = 1
            elif funct3 == 0b100:  # divw
                job.name = "div"
                job.size = 1
            elif funct3 == 0b110:
                job.name = "rem"  # remw
                job.size = 1
        else:
            if funct3 == 0b000:
                if funct7 == 0x00:
                    job.name = "add"  # addw
                    job.size = 1
                elif funct7 == 0x20:
                    job.name = "sub"  # subw
                    job.size = 1
            elif funct3 == 0b001:
                job.name = "sll"  # sllw
                job.size = 1
            elif funct3 == 0b101:
                if funct7 == 0x00:
                    job.name = "srl"  # srlw
                    job.size = 1
                elif funct7 == 0x20:
                    job.name = "sra"  # sraw
                    job.size = 1
    elif opcode in I:  # I-type
        imm_pre = (get_bit(instr, 31, 20))
        imm = sign_expend(imm_pre, 12)
        rs1 = get_bit(instr, 19, 15)
        funct3 = get_bit(instr, 14, 12)
        rd = get_bit(instr, 11, 7)
        job.imm = True
        funct6 = get_bit(instr, 31, 26)
        shamt = get_bit(instr, 25, 20)
        if opcode == 0b0010011:
            if funct3 == 0b000:
                job.name = "add"  # addi
            elif funct3 == 0b010:
                job.name = "slt"  # slti
            elif funct3 == 0b011:
                job.name = "slt"  # sltiu
                job.unsigned = True
                imm = imm_pre
            elif funct3 == 0b100:
                job.name = "xor"  # xori
            elif funct3 == 0b110:
                job.name = "or"  # ori
            elif funct3 == 0b111:
                job.name = "and"  # andi
            elif funct3 == 0b001:
                job.name = "sll"  # slli
                imm = shamt
            elif funct3 == 0b101:
                if funct6 == 0x00:
                    job.name = "srl"  # srli
                    imm = shamt
                elif funct6 == 0x10:
                    job.name = "sra"  # srai
                    imm = shamt
        elif opcode == 0b0000011:
            if funct3 == 0b000:
                job.name = "lb"
                job.do = 2
                job.size = 3
                if rs1 == 2:
                    job.stack = True
            elif funct3 == 0b001:
                job.name = "lh"
                job.do = 2
                job.size = 2
                if rs1 == 2:
                    job.stack = True
            elif funct3 == 0b010:
                job.name = "lw"
                job.do = 2
                job.size = 1
                if rs1 == 2:
                    job.stack = True
            elif funct3 == 0b011:
                job.name = "ld"
                job.do = 2
                if rs1 == 2:
                    job.stack = True
            elif funct3 == 0b100:
                job.name = "lbu"
                job.do = 2
                job.size = 3
                job.unsigned = True
                if rs1 == 2:
                    job.stack = True
                imm = imm_pre
            elif funct3 == 0b101:
                job.name = "lhu"
                job.do = 2
                job.size = 2
                job.unsigned = True
                if rs1 == 2:
                    job.stack = True
                imm = imm_pre
            elif funct3 == 0b110:
                job.name = "lwu"
                job.do = 2
                job.size = 1
                job.unsigned = True
                if rs1 == 2:
                    job.stack = True
                imm = imm_pre
        elif opcode == 0b1100111:
            job.name = "jalr"
            job.do = 3
        elif opcode == 0b1110011:
            if funct3 == 0b000:
                job.name = "ecall"
                job.do = 4
            elif funct3 == 0b001:
                job.name = "csrrw"
                job.do = 4
            elif funct3 == 0b010:
                job.name = "csrrs"
                job.do = 4
            elif funct3 == 0b110:
                job.name = "cssrrsi"
                job.do = 4
        elif opcode == 0b0000111:
            if funct3 == 0b010:
                job.name = "flw"
            elif funct3 == 0b011:
                job.name = "fld"
        elif opcode == 0b0011011:
            if funct3 == 0b000:
                job.name = "add"  # addiw
                job.size = 1
            elif funct3 == 0b001:
                job.name = "sll"  # slliw
                job.size = 1
                imm = shamt
            elif funct3 == 0b101:
                if funct6 == 0x00:
                    job.name = "srl"  # srliw
                    job.size = 1
                    imm = shamt
                elif funct6 == 0x10:
                    job.name = "sra"  # sraiw
                    job.size = 1
                    imm = shamt
    elif opcode == 0b0110111:  # U-type
        job.name = "lui"
        job.imm = True
        job.do = 4
        rd = get_bit(instr, 11, 7)
        imm = get_bit(instr, 31, 12) << 12
    elif opcode == 0b0010111:
        job.name = "auipc"
        job.imm = True
        job.do = 4
        rd = get_bit(instr, 11, 7)
        imm = get_bit(instr, 31, 12) << 12
    elif opcode == 0b1101111:  # J-type
        job.name = "jal"
        job.imm = True
        job.do = 3
        idx_3112 = get_bit(instr, 31, 12)
        imm_pre = (get_bit(idx_3112, 19, 19) << 20) | (get_bit(idx_3112, 7, 0) << 12) | (
                    get_bit(idx_3112, 8, 8) << 11) | (get_bit(idx_3112, 18, 9) << 1)
        imm = sign_expend(imm_pre, 21)
        rd = get_bit(instr, 11, 7)
    elif opcode == 0b0100011:  # S-type
        imm_pre = (get_bit(instr, 31, 25) << 5) | get_bit(instr, 11, 7)
        imm = sign_expend(imm_pre, 12)
        job.imm = True
        rs2 = get_bit(instr, 24, 20)
        rs1 = get_bit(instr, 19, 15)
        funct3 = get_bit(instr, 14, 12)
        if funct3 == 0b000:
            job.name = "sb"
            job.do = 1
            job.size = 3
            if rs1 == 2:
                job.stack = True
        elif funct3 == 0b001:
            job.name = "sh"
            job.do = 1
            job.size = 2
            if rs1 == 2:
                job.stack = True
        elif funct3 == 0b010:
            job.name = "sw"
            job.do = 1
            job.size = 1
            if rs1 == 2:
                job.stack = True
        elif funct3 == 0b011:
            job.name = "sd"
            job.do = 1
            if rs1 == 2:
                job.stack = True
    elif opcode == 0b0100111:
        imm_pre = (get_bit(instr, 31, 25) << 5) | get_bit(instr, 11, 7)
        imm = sign_expend(imm_pre, 12)
        job.imm = True
        rs2 = get_bit(instr, 24, 20)
        rs1 = get_bit(instr, 19, 15)
        funct3 = get_bit(instr, 14, 12)
        if funct3 == 0b010:
            job.name = "fsw"
        elif funct3 == 0b011:
            job.name = "fsd"
    elif opcode == 0b1100011:  # B-type
        rs2 = get_bit(instr, 24, 20)
        rs1 = get_bit(instr, 19, 15)
        funct3 = get_bit(instr, 14, 12)
        idx_3125 = get_bit(instr, 31, 25)
        idx_117 = get_bit(instr, 11, 7)
        imm_pre = (get_bit(idx_3125, 6, 6) << 12) | (get_bit(idx_117, 0, 0) << 11) | (get_bit(idx_3125, 5, 0) << 5) | (
                    get_bit(idx_117, 4, 1) << 1)
        imm = sign_expend(imm_pre, 13)
        job.imm = True
        if funct3 == 0b000:
            job.name = "beq"
            job.do = 3
        elif funct3 == 0b001:
            job.name = "bne"
            job.do = 3
        elif funct3 == 0b100:
            job.name = "blt"
            job.do = 3
        elif funct3 == 0b101:
            job.name = "bge"
            job.do = 3
        elif funct3 == 0b110:
            job.name = "blt"  # bltu
            job.do = 3
            job.unsigned = True
        elif funct3 == 0b111:
            job.name = "bge"  # bgeu
            job.do = 3
            job.unsigned = True

    return job, rs1, rs2, rd, imm


def ID(instr, width, pc: bit_64, rf: registers_file):
    if width == 16:
        job, rs1, rs2, rd, imm = decoder_16(instr)
    else:
        job, rs1, rs2, rd, imm = decoder_32(instr)

    rs1_r, rs2_r = rf.ports_out(rs1, rs2)

#    print("ID: %s   x%d, x%d, x%d %d" % (job.name, rd, rs1, rs2, imm))

    return job, bit_64(rs1_r), bit_64(rs2_r), bit_64(imm), rs1, rs2,  rd, pc, width
